home *** CD-ROM | disk | FTP | other *** search
- (herald (back_end mipsgen)
- (env t (orbit_top defs)))
-
- ;;; Copyright (c) 1985 Yale University
- ;;; Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
- ;;; This material was developed by the T Project at the Yale University Computer
- ;;; Science Department. Permission to copy this software, to redistribute it,
- ;;; and to use it for any purpose is granted, subject to the following restric-
- ;;; tions and understandings.
- ;;; 1. Any copy made of this software must include this copyright notice in full.
- ;;; 2. Users of this software agree to make their best efforts (a) to return
- ;;; to the T Project at Yale any improvements or extensions that they make,
- ;;; so that these may be included in future releases; and (b) to inform
- ;;; the T Project of noteworthy uses of this software.
- ;;; 3. All materials developed as a consequence of the use of this software
- ;;; shall duly acknowledge such use, in accordance with the usual standards
- ;;; of acknowledging credit in academic research.
- ;;; 4. Yale has made no warrantee or representation that the operation of
- ;;; this software will be error-free, and Yale is under no obligation to
- ;;; provide any services, by way of maintenance, update, or otherwise.
- ;;; 5. In conjunction with products arising from the use of this material,
- ;;; there shall be no use of the name of the Yale University nor of any
- ;;; adaptation thereof in any advertising, promotional, or sales literature
- ;;; without prior written consent from Yale in each case.
- ;;;
-
- ;;; GENERATE-HANDLER The situation is that the object is in A1 and its template
- ;;; is in TP. The operation is in P. We must use only the register AN.
-
- (define (hacked-get-register node)
- (cond ((reg-node an) => kill))
- AN)
-
- (define (generate-handler node obj)
- (let ((leaves (call-args (lambda-body ((call-arg 3) (lambda-body node)))))
- (methods (cdddr (call-args (lambda-body node)))))
- (cond ((null? methods)
- (emit mips/jr link-reg)
- (generate-move nil-reg AN))
- (else
- (bind ((get-register hacked-get-register))
- (mark (lambda-self-var *heap-env*) A1)
- (generate-jump (car leaves))
- (let ((last ((call-arg 3) (lambda-body node))))
- (do ((l leaves (cdr l))
- (methods methods (cdr methods)))
- ((null? l)
- (emit-tag last)
- (emit mips/jr link-reg)
- (generate-move nil-reg AN)
- (clear-slots))
- (generate-handler-test obj (car l)
- (car methods)
- (if (null? (cdr l)) last (cadr l))))))))))
-
- (define (generate-handler-test obj leaf method next)
- (emit-tag leaf)
- (let ((el-hacko (cons nil nil)))
- (emit-compare jump-op/jn= (->register nil (leaf-value leaf)) P next el-hacko)
- (emit-tag el-hacko))
- (lambda-queue method)
- (emit risc/add (handler-diff method obj) vector AN) ;entry point in vector
- (emit mips/jr link-reg)
- (emit-noop))
-
-
-
- ;;; %undefined-effect arg = A1
- (define (generate-undefined-effect node)
- (let ((acc (lookup-value node (leaf-value ((call-arg 1) node)))))
- (generate-slink-jump slink/undefined-effect)
- (generate-move acc A1)
- (clear-slots)))
-
-
- ;;; %set vcell = parassign-extra
-
- (define (generate-set node location value)
- (let ((access (if (lambda-node? value)
- (access/make-closure node value)
- (->register node (leaf-value value)))))
- (protect-access access)
- (let ((loc (lookup node (get-lvalue (leaf-value location)) nil))
- (hack1 (cons nil nil))
- (hack2 (cons nil nil)))
- (release-access access)
- (generate-move loc parassign-extra)
- (generate-move access (reg-offset parassign-extra 2))
- (free-register node AN)
- (lock AN)
- (free-register node AN-1)
- (unlock AN)
- (emit risc/load 'ub (reg-offset parassign-extra 0) scratch)
- (emit-compare jump-op/jn= zero scratch hack1 hack2)
- (emit-tag hack1)
- (generate-slink-call slink/set)
- (generate-jump hack2)
- (emit-tag hack2))))
-
-
- (define (generate-remove-state-object node)
- (let ((cont (car (call-args node))))
- (if (and (lambda-node? cont)
- (not (lambda-rest-var cont))
- (variable-refs (lambda-cont-var cont)))
- (mark-continuation node AN+1))))
-
-
- (define (machine-num->register x reg)
- (cond ((16bit? x)
- (emit risc/add (machine-num x) zero reg))
- (else
- (emit mips/lui (unsigned-num
- (fixnum-logand #xffff (fixnum-ashr x 16))) reg)
- (emit risc/or
- (unsigned-num (fixnum-logand #xffff x))
- reg reg))))
-
-
- (define (generate-multiply lvar l-acc r-acc t-reg)
- (cond ((fixnum? lvar)
- (machine-num->register lvar scratch))
- (else
- (emit risc/sra (machine-num 2) l-acc scratch)))
- (emit mips/mult scratch r-acc)
- (emit mips/mflo t-reg))
-
- (define (generate-divide lvar l-acc r-acc t-reg)
- (cond ((fixnum? lvar)
- (generate-move-addressable lvar scratch)
- (emit mips/div scratch r-acc))
- (else
- (emit mips/div l-acc r-acc)))
- (emit mips/mflo scratch)
- (emit risc/sll (machine-num 2) scratch t-reg))
-
- (define (generate-remainder lvar l-acc r-acc t-reg)
- (cond ((fixnum? lvar)
- (generate-move-addressable lvar scratch)
- (emit mips/div scratch r-acc))
- (else
- (emit mips/div l-acc r-acc)))
- (emit mips/mfhi t-reg))
-
- (define (generate-extend node n)
- ;; don't include template
- (generate-move (machine-num (fx- n CELL)) SCRATCH)
- (generate-slink-call slink/make-extend)) ; delay slot
-
-
-
- (define (generate-extra-args-cons len)
- (generate-move (machine-num (* len CELL 2)) SCRATCH)
- (generate-slink-call slink/make-extra-args))
-
-
- (define (generate-extra-arg-move n)
- (generate-move (reg-offset extra-args
- (+ (* (- n *first-stack-register*) 8) 1)) n))
-
- ;;; This stuff almost duplicates code in parassign
- ;;; do-trivial-lambda and indirect-lambda and do-immediate
-
- (define (generate-extra-arg-store node arg n)
- (let ((ro (reg-offset extra-args (+ (* n 8) 1))))
- (cond ((lambda-node? arg)
- (cond ((eq? (environment-closure (lambda-env arg)) *unit*)
- (lambda-queue arg)
- (generate-move (lookup node arg nil) ro))
- (else
- (let ((offset (environment-cic-offset (lambda-env arg))))
- (cond ((fx= offset 0)
- (generate-move AN ro))
- (else
- (generate-move-address (reg-offset AN offset) ro)))))))
- ((not (addressable? (leaf-value arg)))
- (generate-move (lookup-value node (reference-variable arg)) ro))
- (else
- (generate-move-addressable (leaf-value arg) ro)))))
-
- (define (generate-two-fixnums node)
- (destructure (((then else () ref1 ref2) (call-args node)))
- (let ((reg1 (->register node (leaf-value ref1))))
- (lock reg1)
- (let ((reg2 (->register node (leaf-value ref2))))
- (unlock reg1)
- (cond ((target-fixnum? (leaf-value ref2))
- (emit risc/and (machine-num 3) reg1 SCRATCH))
- (else
- (emit risc/or reg1 reg2 SCRATCH)
- (emit risc/and (machine-num 3) SCRATCH SCRATCH)))
- (emit-compare jump-op/jn= SCRATCH zero else then)))))
-
- (define (generate-op-with-overflow node op)
- (destructure (((then else () ref1 ref2) (call-args node)))
- (let ((reg1 (->register node (leaf-value ref1))))
- (lock reg1)
- (let ((reg2 (->register node (leaf-value ref2))))
- (lock reg2)
- (let ((target (get-register node))
- (hack (cons nil nil)))
- (unlock reg1)
- (unlock reg2)
- (xcase op
- ((add)
- (emit mips/addu reg2 reg1 target)
- (emit risc/xor reg2 reg1 scratch)
- (emit-compare jump-op/j>= scratch zero hack then)
- (emit-tag hack)
- (emit risc/xor reg2 target scratch)
- (emit-compare jump-op/j>= scratch zero else then))
- ((subtract)
- (emit mips/subu reg2 reg1 target)
- (emit risc/xor reg2 reg1 scratch)
- (emit-compare jump-op/j>= scratch zero then hack)
- (emit-tag hack)
- (emit risc/xor reg2 target scratch)
- (emit-compare jump-op/j>= scratch zero then else))
- ((multiply)
- (emit risc/sra (machine-num 2) reg1 scratch)
- (emit mips/mult scratch reg2)
- (emit mips/mflo target)
- (emit mips/mfhi scratch)
- (emit risc/sra (machine-num 31) target vector)
- (emit-compare jump-op/jn= scratch vector then else)))
- (mark (car (lambda-variables else)) target))))))
-
- (define (generate-foreign-call node)
- (destructure (((#f foreign rep-list value-rep . args) (call-args node)))
- (emit risc/store 'l sp (reg-offset nil-reg slink/saved-sp))
- (emit risc/store 'l ssp (reg-offset nil-reg slink/saved-ssp))
- (emit risc/store 'l crit-reg (reg-offset nil-reg slink/saved-crit))
- (let* ((rep-list (map cadr (leaf-value rep-list)))
- (replen (length rep-list))
- (bump-bytes (+ (* (max 0 (- replen 4)) 4) 24))) ;24=base stack frame
- (emit risc/sub (machine-num bump-bytes) sSP sSP)
- (emit risc/store 'l link-reg (reg-offset ssp (fx- bump-bytes 4)))
- (cond ((every? (lambda (x) (neq? x 'rep/double)) rep-list)
- (receive (reg-args stack-args)
- (if (fx<= replen 4)
- (return rep-list '())
- (return (nthcdr rep-list (fx- replen 4))
- (reverse (sublist rep-list 0 (fx- replen 4)))))
- (do ((reps stack-args (cdr reps))
- (i 16 (fx+ i 4))
- (in A5 (fx+ in 1)))
- ((null? reps)
- (do ((in (length reg-args) (fx- in 1))
- (out (fx+ (length reg-args) 1) (fx- out 1))
- (reps reg-args (cdr reps)))
- ((null? reps))
- (pointer->rep in out (car reps))
- (lock out)))
- (cond ((fx< in AN)
- (pointer->rep in AN (car reps)))
- (else
- (emit risc/load 'l
- (reg-offset extra-args (+ (* (- in AN) 8) %%car))
- parassign-extra)
- (pointer->rep parassign-extra AN (car reps))))
- (emit risc/store 'l AN (reg-offset ssp i)))))
- ((or (any? (lambda (x) (neq? x 'rep/double)) rep-list)
- (fx> (length rep-list) 2))
- (bug "Can't deal with this mix of float reps"))
- ((null? (cdr rep-list))
- (asemit mips/fload `((reg-offset ,A1 ,double/low-offset) 12))
- (asemit mips/fload `((reg-offset ,A1 ,double/high-offset) 13)))
- (else
- (asemit mips/fload `((reg-offset ,A1 ,double/low-offset) 12))
- (asemit mips/fload `((reg-offset ,A1 ,double/high-offset) 13))
- (asemit mips/fload `((reg-offset ,A2 ,double/low-offset) 14))
- (asemit mips/fload `((reg-offset ,A2 ,double/high-offset) 15))))
- (generate-move (lookup-value node (leaf-value foreign)) an)
- (emit risc/load 'l (reg-offset an 6) an)
- (emit mips/jalr an link-reg)
- (emit mips/noop)
- (generate-move zero extra-args)
- (generate-move zero extra)
- (do ((i a2 (fx+ i 1)))
- ((fx> i an+1))
- (generate-move zero i))
- (emit risc/load 'l (reg-offset ssp (fx- bump-bytes 4)) link-reg)
- (emit risc/add (machine-num bump-bytes) sSP sSP))
- (case (leaf-value value-rep)
- ((rep/undefined ignore)
- (generate-move zero a1)
- (generate-move zero p))
- ((rep/double)
- (generate-move zero p)
- (generate-move (machine-num header/double-float) AN)
- (generate-move (machine-num 8) scratch)
- (generate-slink-call slink/make-extend)
- (asemit mips/fstore `(1 (reg-offset ,AN ,double/high-offset))) ; $f1
- (asemit mips/fstore `(0 (reg-offset ,AN ,double/low-offset))) ; $f0
- (generate-move AN A1)) ; return consed flonum
- (else
- (rep->pointer P A1 (leaf-value value-rep)) ;P = register $2
- (generate-move zero p))))
- (emit risc/store 'l zero (reg-offset nil-reg slink/saved-ssp)))
-
-
- (define (pointer->rep from to rep)
- (case rep
- ((rep/pointer) (generate-move from to))
- ((rep/extend) (emit risc/add (machine-num 2) from to))
- ((rep/c-pointer)
- (emit risc/add (machine-num 2) from to)
- (emit risc/srl (machine-num 2) to to)
- (emit risc/sll (machine-num 2) to to))
- ((rep/string)
- (emit risc/load 'l (reg-offset from 2) vector)
- (emit risc/load 'l (reg-offset from 6) scratch)
- (emit risc/add scratch vector vector)
- (emit risc/add (machine-num 2) vector to))
- ((rep/char)
- (emit risc/srl (machine-num 8) from to))
- (else
- (emit risc/sra (machine-num 2) from to))))
-
- (define (rep->pointer from to rep)
- (case rep
- ((rep/pointer) (generate-move from to))
- ((rep/extend) (emit risc/sub (machine-num 2) from to))
- ((rep/char)
- (emit risc/sll (machine-num 8) from to)
- (emit risc/or (machine-num header/char) to to))
- (else
- (emit risc/sll (machine-num 2) from to))))
-
-